package data

import (
	"context"

	protoV1 "Cosmos.Communication/api/v1"
	"Cosmos.Communication/internal/biz"
	"github.com/go-kratos/kratos/v2/log"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/anypb"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

type invoke struct {
	infrastructure *Data
	logHelper      *log.Helper
}

func NewInvoke(data *Data, logger log.Logger) (d biz.Invoke, cf func(), err error) {
	instance := &invoke{
		infrastructure: data,
	}
	instance.logHelper = log.NewHelper(logger)

	cf = instance.Close
	err = nil
	d = instance
	return
}

func (i *invoke) Invoke(ctx context.Context, request *biz.InvokeRequest) (result *biz.Result[*biz.InvokeResponse], err error) {
	client, err := i.infrastructure.GetVendorRuntimeGrpcClient()
	if err != nil {
		return
	}

	result = &biz.Result[*biz.InvokeResponse]{
		Code: 200,
	}
	rpcRequest := &protoV1.InvokeRequest{
		Type:  &wrapperspb.StringValue{Value: request.Function},
		Param: &wrapperspb.StringValue{Value: request.Parameters},
	}
	rpcResult, err := client.Invoke(ctx, rpcRequest)
	if err != nil {
		return
	}
	if rpcResult == nil {
		result.Code = 500
		result.Message = "Invoke RpcResult is nil"
		return
	}

	result = &biz.Result[*biz.InvokeResponse]{
		Code:    int(rpcResult.Code),
		Message: rpcResult.Message.GetValue(),
		Data:    &biz.InvokeResponse{},
	}
	if rpcResult.Data == nil {
		return
	}
	var rpcInvokeResponse = &protoV1.InvokeResponse{}
	err = anypb.UnmarshalTo(rpcResult.Data, rpcInvokeResponse, proto.UnmarshalOptions{})
	if err != nil {
		return
	}
	result.Data.Value = rpcInvokeResponse.Data.GetValue()
	return
}

func (i *invoke) Close() {
	i.infrastructure.Close()
}
